//============================================================================
// Name        : TP3.cpp
// Author      : 
// Version     :
// Copyright   : 
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include "Controller.h"
#include "Disk.h"
#include "Position.h"
#include "Requisition.h"
#include "Scheduler.h"
#include "SCAN.h"
#include "SSTF.h"
#include "Fifo.h"
#include "PoissonGenerator.h"
#include "Look.h"

using namespace std;

int main() {
	PoissonGenerator pg;
	int numTracks = 100;
	Disk d(numTracks,4,512);
	Look f(numTracks, &d);
//	Fifo f;
	Controller c(&f,&d, &pg, 0.2);
	long double totalTime=0; 
	f.enqueue(Requisition(0,0,1));
	
/*
//	cout << "Enqueuing..." << endl;
	f.enqueue(Requisition(0,0,8*1024));
//	cout << "Enqueuing1..." << endl;
	f.enqueue(Requisition(13,3,18*1024));
//	cout << "Enqueuing2..." << endl;
	f.enqueue(Requisition(7,0,1024));
//	cout << "Enqueuing3..." << endl;
	f.enqueue(Requisition(11,2,1));
//	cout << "Enqueuing4..." << endl;
	

//	cout << "Treating reqs..." << endl;
	c.treatReq();
//	cout << "Treating reqs1..." << endl;
	c.treatReq();
//	cout << "Treating reqs2..." << endl;
	c.treatReq();
//	cout << "Treating reqs3..." << endl;
	c.treatReq();
	cout << "Treating reqs4..." << endl;*/
	
	
	/*
	for(int i=0;i<800;i++)		
	{
		//cout << "oi i=" << j << endl;
		for(int j=0; j< 40; j++)	
		{
//			cout << "oi 1" << endl;
			Position p = c.addressConv(i*40 +j);
			pg.enqueue(Requisition(p.track,p.sector,1));
			pg.enqueue(Requisition(p.track,p.sector,1));
//			cout << "oi 2" << endl;
			//cache.write(val, i*100+j);
//			cout << "no Address: " << i*100+j << endl;
		}
	} 
	*/
	
	/*
	for (int i = 0; i < 100; i = i+1) {
		//cout << "i2 = " << i << endl;
		for (int j = 0; j < 100; j = j+1){
			Position p1 = c.addressConv(i*100+j);
			Position p2 = c.addressConv(i*100+j+10000);
			Position p3 = c.addressConv(i*100+j+20000);
			pg.enqueue(Requisition(p1.track,p1.sector,1));
			pg.enqueue(Requisition(p2.track,p2.sector,1));
			pg.enqueue(Requisition(p3.track,p3.sector,1));
			//uint val = cache.read(i*500+j);
			//uint val1 = cache.read(i*500+j+150000);
			//cache.write(val1+val, i*500+j+300000);
		}
	
	} 
	*/
	
		//BLOCKING AFTER
		long long contadorFeliz = 0;
		int N = 40;
		for(int B=8;B<=8;B++){
			for (int jj = 0; jj < N; jj = jj+B) {
				//cout << "jj = " << jj << endl;
				for (int kk = 0; kk < N; kk = kk+B)
					for (int i = 0; i < N; i = i+1)
						for (int j = jj; j < min(jj+B,N); j = j+1)
						{
							Position p1 = c.addressConv(33000);
							pg.enqueue(Requisition(p1.track,p1.sector,1));
							contadorFeliz++;
							//cache.write(0,270000);
							for (int k = kk; k < min(kk+B,N); k = k+1) 
							{
								p1 = c.addressConv(i*N+k+10000);
								pg.enqueue(Requisition(p1.track,p1.sector,1));
								//uint val = cache.read(i*N+k+300000);
								p1 = c.addressConv(k*N+j+20000);
								pg.enqueue(Requisition(p1.track,p1.sector,1));
								//val += cache.read(k*N+j+600000);
								p1 = c.addressConv(33000);
								pg.enqueue(Requisition(p1.track,p1.sector,1));
								//val += cache.read(270000);
								p1 = c.addressConv(33000);
								pg.enqueue(Requisition(p1.track,p1.sector,1));
								//cache.write(val,270000);
								contadorFeliz += 4;
							}
							p1 = c.addressConv(35000);
							pg.enqueue(Requisition(p1.track,p1.sector,1));
							//uint val1 = cache.read(270000);
							p1 = c.addressConv(N*i+j);
							pg.enqueue(Requisition(p1.track,p1.sector,1));
							//val1+= cache.read(N*i+j);
							p1 = c.addressConv(N*i+j);
							pg.enqueue(Requisition(p1.track,p1.sector,1));
							//cache.write(val1,N*i+j);
							contadorFeliz += 3;
						} }
			//cout << "B = "<< B << " missRate = " << cache.getMissCounter() << endl;
			//cache.clear();
		} 
		cout << "Contador feliz: " << contadorFeliz << endl;
		
	for(int kkkk=0;kkkk<contadorFeliz; kkkk++) {
		if (kkkk % 83947 == 75328)
			cout << "kkkk: " << kkkk << endl;
		totalTime +=c.treatReq();
	}
	
	cout << "Tempo final: " << totalTime << endl; 
	
	return 0;
}
